#pragma once

#include "activeobject.h"

namespace RoomFW {

//
// Class:	ActiveHSM
//
// Description:	ActiveObject derived Hierarchical State Machine
//
// Author:	Andrew Sage
//
class ActiveHSM : public QHsm, public ActiveObject
{
public:

	//
	// Method:	ActiveHSM
	//
	// Description:	Constructor
	//
	// Parameters:
	//
	//	initialState - QHsm constructor arguement.
	//
	//	portCount, timer, ownTimer - ActiveObject constructor arguements.
	//
	ActiveHSM(QSTATE initialState, size_t portCount, const PortPriorityArray& portPriority);

	//
	// Method:	~ActiveHSM
	//
	// Description:	Destructor
	//
	virtual ~ActiveHSM(void);

protected:

	//
	// Method:	initializeThread
	//
	// Description:	v override to initialize QHsm once thread is running.
	//
	// Parameters:	None.
	//
	// Return:	None
	//
	virtual bool initializeThread(void);

	//
	// Method:	handle
	//
	// Description:	ActiveObject override to pass message to QHsm::dispatch().
	//
	// Parameters:
	//
	//	message - RoomMessage to handle.
	//
	// Return:	None
	//
	virtual void handle(RoomMessageSP message);

	//
	// Method:	getCurrentMessage
	//
	// Description:	Allow ActiveHSM's access to the actual RoomMessageSP, not just the bare
	//              pointer
	//
	// Parameters: None
	//
	// Return:
	//
	//	message - current RoomMessage being handled;
	//
	RoomMessageSP getCurrentMessage();

protected:

	//
	// Signal used to do a state transition from outside the state machine.
	//
	struct QErrorTranSig : public QEvent
	{
		QErrorTranSig(QSTATE dest);
		QSTATE dest_;
	};

	//
	// Used to do a state transition from outside state machine.
	// Use the ERROR_TRAN macro form DefaultErrorReporting.h
	//
	void errorTran(QSTATE dest);

	//
	// Top-level state to handle Q_ERROR_TRAN.
	//
	static QSTATE top(ActiveHSM* me, QEvent const *evt);

	//
	// Get current state before handling message.  Used in error macros.
	//
	QSTATE getCurrentState();

private:

	RoomMessageSP currentMessage_;
	QSTATE currentState_;
};




/// This function is here for those times when you want to set a breakpoint in the Q_TRAN_LOG macro.
/// Implementation is in ActiveHSM.cpp -- set your breakpoint there.
extern void Q_TRAN_LOG_breakHook();

/** Transition to the request QSTATE function and log that it happened.
 \note This macro assumes you have a functionName constant initialized with the name of the containing function.
 \param newStateFunction The name symbol (not string) of the function implementing the new state.
 \note This macro invokes 2 other macros.  Be careful when making changes. Preprocessor output will help if you have to debug it.
  
 Example:  \verbatim
     QSTATE CoordinatorHSM::QPSH_idle(CoordinatorHSM* me, QEvent const *e)
     {
         ...
     }
     QSTATE CoordinatorHSM::QPSH_operational(CoordinatorHSM* me, QEvent const *e)
     {
          static const char* functionName = "CoordinatorHSM::QPSH_operational";
          . . .
          Q_TRAN_LOG(CoordinatorHSM::QPSH_idle);
 \endverbatim
 will result in a log line like this:     <table><tr><td>

 <TRACE><347926.328784><CoordinatorHSM.cpp(823)><Q_TRAN: CoordinatorHSM::QPSH_operational ==> CoordinatorHSM::QPSH_idle>

     </td></tr></table>
 */
#define Q_TRAN_LOG(newStateFunction) \
	Q_TRAN(reinterpret_cast<QSTATE>(&newStateFunction)); \
	G_LOG_1_TRACE("Q_TRAN ==> %s", #newStateFunction);	\
	me->statusHandler_.setStatus("HSM_State", #newStateFunction); \
	RoomFW::Q_TRAN_LOG_breakHook();

}
